//    Copyright (C) Kherty.  All rights reserved.
using System;

namespace OpenLS.Spreadsheet.StandardAddIn.Statistics
{
    internal class BinomialDistribution : IntegerDistribution
    {
        private double _probabilityOfSuccess;
        private int _trialCount;

        public BinomialDistribution(int trials, double probabilityOfSuccess)
        {
            TrialCount = trials;
            ProbabilityOfSuccess = (probabilityOfSuccess);
        }

        public int TrialCount
        {
            get { return _trialCount; }
            set
            {
                if (!IsValidTrialCount(value))
                    throw new ArgumentOutOfRangeException("value");
                _trialCount = value;
            }
        }

        public double ProbabilityOfSuccess
        {
            get { return _probabilityOfSuccess; }
            set
            {
                CheckValidProperty(value);
                _probabilityOfSuccess = value;
            }
        }

        public static bool IsValidTrialCount(int value)
        {
            return value >= 0;
        }

        protected override int DomainLowerBound(double p)
        {
            return -1;
        }

        protected override int DomainUpperBound(double p)
        {
            return TrialCount;
        }

        public override double CumulativeProbability(int x)
        {
            if (x < 0)
                return 0.0;
            else if (x >= TrialCount)
                return 1.0;
            else
                return 1.0 - Statistician.RegularizedBeta(ProbabilityOfSuccess, x + 1.0, TrialCount - x);
        }

        public override double Probability(int x)
        {
            if (x < 0 || x > TrialCount)
                return 0.0;
            else
                return Statistician.BinomialCoefficientDouble(
                           TrialCount, x)*
                       Math.Pow(ProbabilityOfSuccess, x)*
                       Math.Pow(1.0 - ProbabilityOfSuccess,
                                TrialCount - x);
        }

        public override int InverseCumulativeProbability(double probability)
        {
            if (probability == 0)
                return -1;
            if (probability == 1)
                return int.MaxValue;
            return base.InverseCumulativeProbability(probability);
        }
    }
}